package com.atguigu.juc.day01;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author atguigu-mqx
 */
//  编写一个有问题的读写测试！
class MyCache {
    //  声明一个map 集合 充当缓存！ volatile: 被它修饰的变量，在多线程情况下，这个变量是可见的！
    private volatile Map<String, String> map = new HashMap<>();

    //  声明读写锁！
    final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

    //  写入方法
    public void put(String key, String value) {
        //  开始上锁：
        rwl.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "开始写入....");
            map.put(key, value);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "写入完成....");
        } finally {
            //  解锁
            rwl.writeLock().unlock();
        }
    }

    //  读取方法
    public void get(String key) {
        //  读写锁必须使用同一个对象：
        rwl.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "开始读取....");
            String value = map.get(key);
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "读取完成...." + value);
        } finally {
            //  解锁：
            rwl.readLock().unlock();
        }
    }

    public void test(){
        rwl.writeLock().lock();
        System.out.println("获取写锁");
        rwl.readLock().lock();
        System.out.println("获取读锁");
        rwl.writeLock().unlock();
        System.out.println("释放写锁------");
        rwl.readLock().unlock();
        System.out.println("释放读锁------");
    }
}

public class ReentrantReadWriteLockDemo {

    //  主入口：
    public static void main(String[] args) {
        //  线程操作资源类，高内聚低耦合！
        MyCache myCache = new MyCache();
        myCache.test();
        //        //  创建写入线程执行！
        //        for (int i = 1; i <= 10; i++) {
        //            //  声明一个变量
        //            String num = i + "";
        //            new Thread(() -> {
        //                myCache.put(num, num);
        //            }, String.valueOf(i)).start();
        //        }
        //
        //        //  创建读取线程执行！
        //        for (int i = 1; i <= 10; i++) {
        //            //  声明一个变量
        //            String num = i + "";
        //            new Thread(() -> {
        //                myCache.get(num);
        //            }, String.valueOf(i)).start();
        //        }
    }
}
